﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ST.Buz.Base;
using ST.Buz.Base.Entity;
using ST.Buz.Base.Enums;
using ST.Buz.Base.ViewModel;
using ST.Common.Util;
using ST.Common.Util.Model;
using ST.Common.Util.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ST.Buz.Service
{
	public partial interface IServiceFinanceRecv
	{
		PageData GetPageList(VMS_IMS_FinanceRecv searchModel, UserSession sessionCurrent);

		int GetCount(VMS_IMS_FinanceRecv searchModel, UserSession sessionCurrent);

		IMS_FinanceRecv GetViewDetail(int id, UserSession sessionCurrent);

		IMS_FinanceRecv GetEditDetail(int id, UserSession sessionCurrent);

		int AddOrUpdate(IMS_FinanceRecv model, UserSession sessionCurrent);

		int AddOrUpdateWithinTrans(IMS_FinanceRecv model, UserSession sessionCurrent);

		bool Delete(int id, UserSession sessionCurrent);

		bool BatchDelete(int[] ids, UserSession sessionCurrent);

		string NextSNo();
	}

	public partial class ServiceFinanceRecv
	{
		private readonly IServiceFinanceRecvDetail serviceDetail;
		private readonly IServiceFinanceRecvDue serviceRecvDue;
		private readonly IServiceSysLog serviceSysLog;

		public ServiceFinanceRecv(BuzContext ctx,
			IServiceFinanceRecvDetail _serviceDetail,
			IServiceFinanceRecvDue _serviceRecvDue,
			IServiceSysLog _serviceSysLog,
			ILogger<ServiceFinanceRecv> log)
		{
			serviceDetail = _serviceDetail;
			serviceRecvDue = _serviceRecvDue;
			serviceSysLog = _serviceSysLog;
			context = ctx;
			logger = log;
		}

		private IQueryable<IMS_FinanceRecv> GetQuery(VMS_IMS_FinanceRecv searchModel, UserSession sessionCurrent)
		{
			var query = from m in context.FinanceRecv
						select m;
			if (!string.IsNullOrWhiteSpace(searchModel.sno))
			{
				query = query.Where(m => m.SNo == searchModel.sno);
			}
			if (searchModel.dueid.HasValue && searchModel.dueid.Value > 0)
			{
				var detailQuery = from d in context.FinanceRecvDetail
								  where d.DueID == searchModel.dueid.Value
								  select d.RecvID;
				var ids = detailQuery.ToArray();
				if (ids != null && ids.Length > 0)
				{
					query = query.Where(m => ids.Contains(m.ID));
				}
				else
				{
					query = query.Where(m => false);
				}
			}
			if (searchModel.partnerid.HasValue && searchModel.partnerid.Value > 0)
			{
				query = query.Where(m => m.PartnerID == searchModel.partnerid.Value);
			}
			else if (!string.IsNullOrEmpty(searchModel.partnername))
			{
				query = query.Where(m => EF.Functions.Like(m.PartnerName, "%" + searchModel.partnername + "%"));
			}

			if (searchModel.date_s != DateTime.MinValue)
			{
				query = query.Where(m => m.RecvDate >= searchModel.date_s);
			}
			if (searchModel.date_e != DateTime.MinValue)
			{
				query = query.Where(m => m.RecvDate <= searchModel.date_e);
			}
			if (searchModel.state != null && searchModel.state.Length > 0)
			{
				if (searchModel.state.Length == 1)
				{
					query = query.Where(m => m.StateNow == searchModel.state[0]);
				}
				else
				{
					query = query.Where(m => searchModel.state.Contains(m.StateNow));
				}
			}
			if (searchModel.orgids != null && searchModel.orgids.Length > 0)
			{
				query = searchModel.orgids.Length == 1 ? query.Where(m => m.OrgID == searchModel.orgids[0]) : query.Where(m => searchModel.orgids.Contains(m.OrgID));
			}
			return query;
		}

		/// <summary>
		/// 分页列表
		/// </summary>
		public PageData GetPageList(VMS_IMS_FinanceRecv searchModel, UserSession sessionCurrent)
		{
			PageData result = null;
			try
			{
				searchModel.Validate();

				result = new PageData(searchModel.pnum.Value, searchModel.psize.Value);
				var query = GetQuery(searchModel, sessionCurrent);
				var sumCol = new string[] { "TotalRecv" };
				object[] sumTotal = null;
				var sumResult = (from q in query
								 select new
								 {
									 TotalRecv = query.Sum(m => m.TotalRecv),
									 Count = query.Count(),
								 }).FirstOrDefault();
				if (sumResult == null)
				{
					sumTotal = new object[] { 0M };
				}
				else
				{
					sumTotal = new object[] {
						sumResult.TotalRecv,
					};
					result.total = sumResult.Count;
				}
				switch (searchModel.sortby)
				{
					default:
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.ID) : query.OrderByDescending(e => e.ID);
						break;
				}
				result.LoadList(query);
				result.sumtotal = sumTotal;
				result.sumcol = sumCol;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取分页数据出错");
				throw new BuzException("获取分页数据失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return result;
		}

		public int GetCount(VMS_IMS_FinanceRecv searchModel, UserSession sessionCurrent)
		{
			try
			{
				var query = GetQuery(searchModel, sessionCurrent);

				return query.Count();
			}
			catch (ArgumentNullException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw new BuzException(ex.Message, ex);
			}
		}

		/// <summary>
		/// 获取详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public IMS_FinanceRecv GetViewDetail(int id, UserSession sessionCurrent)
		{
			IMS_FinanceRecv model = null;
			try
			{
				model = Get(id, true);
				if (model == null)
				{
					throw new BuzException("参数不能为空");
				}
				model.Details = serviceDetail.GetDetailList(model.ID, sessionCurrent);
			}
			catch (ArgumentException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取对象信息出错");
				throw new BuzException("获取对象信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return model;
		}

		/// <summary>
		/// 获取详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public IMS_FinanceRecv GetEditDetail(int id, UserSession sessionCurrent)
		{
			return GetViewDetail(id, sessionCurrent);
		}

		/// <summary>
		/// 新增或修改保存
		/// </summary>
		public int AddOrUpdate(IMS_FinanceRecv model, UserSession sessionCurrent)
		{
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}
				if (model == null)
				{
					throw new BuzException("参数不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						var rowID = AddOrUpdateWithinTrans(model, sessionCurrent);

						trans.Commit();

						return rowID;
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "保存对象信息出错");
				throw new BuzException("数据库保存失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}
		public int AddOrUpdateWithinTrans(IMS_FinanceRecv model, UserSession sessionCurrent)
		{
			#region 事务具体操作
			DateTime dtNow = DateTime.Now;
			string ip = GetRequestIP();
			List<int> lstDueID = new List<int>();
			List<IMS_FinanceRecvDue> lstDue = null;
			int i, j;

			#region 获取应收款信息
			if (model.Details != null)
			{
				for (i = 0; i < model.Details.Count; i++)
				{
					if (model.Details[i].DueRecv == null)
					{
						throw new BuzException("第" + (i + 1) + "行应收款信息为空");
					}
					if (lstDueID.Contains(model.Details[i].DueRecv.ID))
					{
						throw new BuzException("第" + (i + 1) + "行编号为[" + model.Details[i].DueSNo + "]的应收款信息重复");
					}
					lstDueID.Add(model.Details[i].DueRecv.ID);
				}
				lstDue = context.FinanceRecvDue.Where(m => lstDueID.Contains(m.ID)).OrderBy(m => m.ID).AsNoTracking().ToList();
				for (i = 0; i < model.Details.Count; i++)
				{
					model.Details[i].DueID = 0;
					for (j = 0; j < lstDue.Count; j++)
					{
						if (model.Details[i].DueRecv.ID == lstDue[j].ID)
						{
							model.Details[i].DueRecv = lstDue[j];
							model.Details[i].DueID = lstDue[j].ID;
							model.Details[i].DueSNo = lstDue[j].SNo;
							break;
						}
					}
					if (model.Details[i].DueID == 0)
					{
						throw new BuzException("第" + (i + 1) + "行编号为[" + model.Details[i].DueSNo + "]的应收款信息不存在");
					}
				}
			}
			#endregion

			if (model.ID > 0)
			{
				Update(model);

				var detailQuery = from d in context.FinanceRecvDetail
								  where d.RecvID == model.ID
								  select d;
				var lstDueOld = detailQuery.OrderBy(m => m.ID).AsNoTracking().ToList();
				var deleted = lstDueOld.Except(model.Details, new Sys_Compare_RowID<IMS_FinanceRecvDetail>());//找出删掉的
				foreach (var d in deleted)
				{
					if (!lstDueID.Contains(d.DueID))
					{
						lstDueID.Add(d.DueID);
					}
					serviceDetail.Delete(d.ID);//删除新列表中不存在的
				}

				if (model.Details != null)
				{
					#region 处理明细收款金额
					for (i = 0; i < model.Details.Count; i++)
					{
						for (j = 0; j < lstDueOld.Count; j++)
						{
							if (lstDueOld[j].DueID == model.Details[i].DueID)
							{
								model.Details[i].DueRecv.TotalRecved -= lstDueOld[j].Recved;//要把关联的应收款的已付金额减去
								break;
							}
						}
					}
					switch (model.ShareType)
					{
						case (int)FinanceShareType.不自动分配:
							{
								decimal total = 0;
								for (i = 0; i < model.Details.Count; i++)
								{
									if (model.Details[i].DueRecv.TotalRecvLeft < model.Details[i].Recved)
									{
										throw new BuzException("第" + (i + 1) + "行收款金额超过应收款剩余应收金额");
									}
									total += model.Details[i].Recved;
								}
								if (total != model.TotalRecv)
								{
									throw new BuzException("收款金额与应收款明细总额不一致");
								}
							}
							break;
						case (int)FinanceShareType.按应收付款先后顺序:
							{
								decimal total = model.TotalRecv;
								for (i = 0; i < model.Details.Count; i++)
								{
									model.Details[i].Recved = 0;//先重置收款信息
								}
								for (i = 0; i < lstDueOld.Count; i++)//优先付之前的记录
								{
									for (j = 0; j < model.Details.Count; j++)
									{
										if (model.Details[j].DueID == lstDueOld[i].DueID)
										{
											break;
										}
									}
									if (j < model.Details.Count)
									{
										model.Details[j].Recved = total < model.Details[j].DueRecv.TotalRecvLeft ? total : model.Details[j].DueRecv.TotalRecvLeft;
										model.Details[j].DueRecv.TotalRecved += model.Details[j].Recved;
										total -= model.Details[j].Recved;
									}
								}
								for (i = 0; i < model.Details.Count; i++)
								{
									if (total <= 0)
									{
										break;
									}
									if (model.Details[i].DueRecv.TotalRecvLeft <= 0)
									{
										continue;
									}
									model.Details[i].Recved = total < model.Details[i].DueRecv.TotalRecvLeft ? total : model.Details[i].DueRecv.TotalRecvLeft;
									total -= model.Details[i].Recved;
								}
							}
							break;
						case (int)FinanceShareType.平均分配总金额:
							{

							}
							break;
						case (int)FinanceShareType.按应收付款比例:
							{

							}
							break;
					}
					#endregion

					for (i = 0; i < model.Details.Count; i++)
					{
						model.Details[i].RecvID = model.ID;

						if (model.Details[i].ID > 0)
						{
							if (model.Details[i].Recved == 0)
							{
								serviceDetail.Delete(model.Details[i]);
							}
							else
							{
								serviceDetail.Update(model.Details[i]);
							}
						}
						else
						{
							if (model.Details[i].Recved == 0)
							{
								continue;
							}
							model.Details[i].DetailAddDate = model.AddDate;
							serviceDetail.Add(model.Details[i]);
						}
					}
				}

				#region 更新应收款
				if (lstDueID.Count > 0)
				{
					serviceRecvDue.UpdateDue(lstDueID.ToArray(), sessionCurrent);
				}
				#endregion
			}
			else
			{
				model.AddDate = dtNow;
				model.AddManID = sessionCurrent.UserID;
				model.AddManName = sessionCurrent.UserName;
				model.SNo = NextSNo();
				model.OrgID = sessionCurrent.OrgID;
				Add(model);
				if (model.Details != null)
				{
					#region 处理明细收款金额
					switch (model.ShareType)
					{
						case (int)FinanceShareType.不自动分配:
							{
								decimal total = 0;
								for (i = 0; i < model.Details.Count; i++)
								{
									if (model.Details[i].DueRecv.TotalRecvLeft < model.Details[i].Recved)
									{
										throw new BuzException("第" + (i + 1) + "行收款金额超过应收款剩余应收金额");
									}
									total += model.Details[i].Recved;
								}
								if (total != model.TotalRecv)
								{
									throw new BuzException("收款金额与应收款明细总额不一致");
								}
							}
							break;
						case (int)FinanceShareType.按应收付款先后顺序:
							{
								decimal total = model.TotalRecv;
								for (i = 0; i < model.Details.Count; i++)
								{
									if (total <= 0)
									{
										model.Details[i].Recved = 0;
										continue;
									}
									if (model.Details[i].DueRecv.TotalRecvLeft <= 0)
									{
										continue;
									}
									model.Details[i].Recved = total < model.Details[i].DueRecv.TotalRecvLeft ? total : model.Details[i].DueRecv.TotalRecvLeft;
									total -= model.Details[i].Recved;
								}
							}
							break;
						case (int)FinanceShareType.平均分配总金额:
							{

							}
							break;
						case (int)FinanceShareType.按应收付款比例:
							{

							}
							break;
					}
					#endregion
					for (i = 0; i < model.Details.Count; i++)
					{
						if (model.Details[i].Recved == 0)
						{
							continue;
						}
						model.Details[i].RecvID = model.ID;
						model.Details[i].DetailAddDate = model.AddDate;

						serviceDetail.Add(model.Details[i]);
					}
					#region 更新应收款
					if (lstDue.Count > 0)
					{
						serviceRecvDue.UpdateDue(lstDueID.ToArray(), sessionCurrent);
					}
					#endregion
				}
			}
			#endregion
			return model.ID;
		}

		/// <summary>
		/// 删除具体操作
		/// </summary>
		/// <param name="id"></param>
		/// <param name="ip"></param>
		/// <param name="dtNow"></param>
		/// <param name="sessionCurrent"></param>
		protected void DeleteWithinTrans(int id, string ip, DateTime dtNow, UserSession sessionCurrent)
		{

			IMS_FinanceRecv modelOld = Get(id, true);

			var dueIDs = (from m in context.FinanceRecvDetail
						  where m.RecvID == id
						  select m.DueID).ToArray();
			context.Database.ExecuteSqlInterpolated($"DELETE FROM IMS_FinanceRecvDetail WHERE RecvID={id}");

			if (dueIDs != null && dueIDs.Length > 0)
			{
				serviceRecvDue.UpdateDue(dueIDs, sessionCurrent);
			}

			Delete(modelOld);
			serviceSysLog.Add(sessionCurrent, ip, $"删除编号为[{modelOld.SNo}]的收款单信息，原信息：", modelOld, dtNow);
		}

		/// <summary>
		/// 删除用户
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public bool Delete(int id, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						DeleteWithinTrans(id, ip, dtNow, sessionCurrent);
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "删除收款单信息出错");
				throw new BuzException("删除收款单信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 批量删除用户
		/// </summary>
		/// <returns></returns>
		public bool BatchDelete(int[] ids, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				if (ids == null || ids.Length == 0)
				{
					throw new BuzException("参数不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						foreach (int id in ids)
						{
							DeleteWithinTrans(id, ip, dtNow, sessionCurrent);
						}
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "批量删除收款单信息出错");
				throw new BuzException("批量删除收款单信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 获取下一个流水号
		/// </summary>
		/// <returns></returns>
		public string NextSNo()
		{
			try
			{
				DateTime dtNow = DateTime.Now;
				string prefix = "S-" + DateTime.Now.ToString("yyyyMMdd-");
				string maxSNo = context.FinanceRecv.Where(m => EF.Functions.Like(m.SNo, prefix + "%")).Max(m => m.SNo);
				int maxNo = 0;
				if (!string.IsNullOrEmpty(maxSNo))
				{
					int.TryParse(maxSNo.Substring(prefix.Length), out maxNo);
				}

				return prefix + (maxNo + 1).ToString().PadLeft(4, '0');
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw new BuzException(ex.Message, ex);
			}
		}
	}
}